package com.dcits.business.server.dubbo;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.net.telnet.TelnetClient;
import org.apache.log4j.Logger;

import com.alibaba.fastjson.annotation.JSONField;
import com.dcits.business.server.ViewServerInfo;
import com.dcits.tool.StringUtils;

public class DubboServer extends ViewServerInfo {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public static final String SERVER_TYPE_NAME = "dubbo";
	
	public static final Character lastChar = '>';
	public static final String endingTag = "dubbo>";
	
	public static final int connectTimeout = 5000;
	public static final int soTimeout = 10000;
	
	private static final Logger logger = Logger.getLogger(DubboServer.class);
	
	private static final Map<String, Object> alertThreshold = new HashMap<String, Object>();
	
	static {
		alertThreshold.put("memoryUsedPercent", 100);
		alertThreshold.put("threadActiveCount", 500);
	}

	@JSONField(serialize=false)
	private TelnetClient client;
	@JSONField(serialize=false)
	private PrintStream out;
	@JSONField(serialize=false)
	private InputStream in;
	
	
	public DubboServer() {
		// TODO Auto-generated constructor stub
		super(new DubboMonitoringInfo());
	}
	
	
	@Override
	public String connect() {
		// TODO Auto-generated method stub
		try {
			createSocketConnection();
		} catch (Exception e) {
			// TODO: handle exception
			logger.error(this.getHost() + ":" + this.getPort() + "创建telnet连接失败", e);
			return this.getHost() + ":" + this.getPort() + "创建telnet连接失败:" + (e.getMessage() == null ? "" : e.getMessage());
		}
		return "true";
	}

	@Override
	public boolean disconect() {
		// TODO Auto-generated method stub
		try {
			if (this.in != null) this.in.close();
			if (this.out != null) this.out.close();
			if (this.client != null) this.client.disconnect(); 			
		} catch (Exception e) {
			// TODO: handle exception
			logger.error("断开dubbo-telnet连接失败!", e);
		}		
		return true;
	}

	@Override
	public void getMonitoringInfo() {
		// TODO Auto-generated method stub
		try {
			parseInfo(request("status -l"));
		} catch (Exception e) {
			// TODO: handle exception
			logger.error("dubbo-telnet接收信息失败!", e);
		}
		
	}
	public String request(String requestInfo) throws IOException {
		StringBuilder replyMessage = new StringBuilder("");
		this.out.println(requestInfo);
		this.out.flush();
		try {
			char ch = (char) in.read(); 
			while (true) {  
				replyMessage.append(ch);
				 if (ch == lastChar) {  
	                 if (replyMessage.toString().endsWith(endingTag)) {  
	                     return replyMessage.toString();
	                 }  
	             } 
				 ch = (char) in.read(); 
			}
		} catch (Exception e) {
			// TODO: handle exception
			logger.error("dubbo-telnet接收信息失败!", e);
		}
		return null;
		  
	}
	
	/*+------------+--------+--------------------------------------------------------+
	| resource   | status | message                                                |
	+------------+--------+--------------------------------------------------------+
	| load       | OK     | load:0.38,cpu:48                                       |
	| server     | OK     | /10.243.23.12:10150(clients:9)                         |
	| threadpool | OK     | Pool status:OK, max:300, core:300, largest:300, active:1, task:346473, service port: 10150 |
	| memory     | OK     | max:4088M,total:4088M,used:2431M,free:1657M            |
	| registry   | OK     | 10.243.23.22:2181(connected),10.243.23.23:2181(connected),10.243.23.21:2181(connected) |
	| summary    | OK     |                                                        |
	+------------+--------+--------------------------------------------------------+*/
	private void parseInfo(String info) {
		DubboMonitoringInfo monitoringInfo = (DubboMonitoringInfo) this.getInfo();
		if (StringUtils.isNotEmpty(info)) {
			for (String line:info.split("\\n")) {
				if (line.indexOf("load") != -1) {
					monitoringInfo.setLoadStatus(line.substring(1, line.length() - 1).split("\\|")[1].trim());
				}
				
				if (line.indexOf("server") != -1) {
					monitoringInfo.setServerStatus(line.substring(1, line.length() - 1).split("\\|")[1].trim());
				}
				
				if (line.indexOf("threadpool") != -1) {
					String[] infos = line.substring(1, line.length() - 1).split("\\|");
					monitoringInfo.setThreadStatus(infos[1].trim());
					String[] threadInfos = infos[2].split(",");
					monitoringInfo.setThreadMaxCount(threadInfos[1].split(":")[1].trim());
					monitoringInfo.setThreadCoreCount(threadInfos[2].split(":")[1].trim());
					monitoringInfo.setThreadLargestCount(threadInfos[3].split(":")[1].trim());
					monitoringInfo.setThreadActiveCount(threadInfos[4].split(":")[1].trim());
					monitoringInfo.setThreadTaskCount(threadInfos[5].split(":")[1].trim());				
				}
				
				if (line.indexOf("memory") != -1) {
					String[] infos = line.substring(1, line.length() - 1).split("\\|");
					monitoringInfo.setMemoryStatus(infos[1].trim());
					String[] memoryInfos = infos[2].split(",");
					monitoringInfo.setMemoryMax(memoryInfos[0].split(":")[1].replace("M", "").trim());
					monitoringInfo.setMemoryTotal(memoryInfos[1].split(":")[1].replace("M", "").trim());
					monitoringInfo.setMemoryUsed(memoryInfos[2].split(":")[1].replace("M", "").trim());
					monitoringInfo.setMemoryFree(memoryInfos[3].split(":")[1].replace("M", "").trim());
					monitoringInfo.setMemoryUsedPercent(String.valueOf(Integer.valueOf(monitoringInfo.getMemoryUsed()) * 100 / Integer.valueOf(monitoringInfo.getMemoryTotal())));
				}
				
				if (line.indexOf("registry") != -1) {
					monitoringInfo.setRegistryStatus(line.substring(1, line.length() - 1).split("\\|")[1].trim());
				}
				
				if (line.indexOf("summary") != -1) {
					monitoringInfo.setSummaryStatus(line.substring(1, line.length() - 1).split("\\|")[1].trim());
				}
				
				if (line.indexOf("spring") != -1) {
					monitoringInfo.setSpringStatus(line.substring(1, line.length() - 1).split("\\|")[1].trim());
				}
			}			
			monitoringInfo.setTime(new Date());
			this.connectStatus = "true";
		} else {			
			this.connectStatus = "获取信息失败!";					
		}
	}
	
	private void createSocketConnection() throws IOException {
		this.client = new TelnetClient();
		this.client.connect(this.getHost(), this.getPort());
		this.client.setConnectTimeout(connectTimeout);
		this.client.setSoTimeout(soTimeout);
		this.out = new PrintStream(this.client.getOutputStream());
		this.in = this.client.getInputStream();
	}
	
	public TelnetClient getClient() {
		return client;
	}
	public void setClient(TelnetClient client) {
		this.client = client;
	}
	public PrintStream getOut() {
		return out;
	}
	public void setOut(PrintStream out) {
		this.out = out;
	}
	public InputStream getIn() {
		return in;
	}
	public void setIn(InputStream in) {
		this.in = in;
	}

}
